package main

import (
	"fmt"
	"net/http"
	"sync/atomic"
	"time"
	"unsafe"
)

type CASRedPackets struct {
	GiveMoney              *float64
	redPacketStatisticsPtr *unsafe.Pointer
}

func NewCASRedPackets() *CASRedPackets {
	cas := &CASRedPackets{}
	val := unsafe.Pointer(&RedPacketStatistics{})
	ptr := &val
	cas.redPacketStatisticsPtr = ptr
	atomic.StorePointer(ptr, val)
	return cas
}

func (cas CASRedPackets) GrabHandler(w http.ResponseWriter, r *http.Request) {
	for ; ; {
		var (
			responseMap                                    = make(map[string]interface{})
			oldRedPacketStatistics, newRedPacketStatistics RedPacketStatistics
		)

		oldRedPacketStatistics = *(*RedPacketStatistics)(atomic.LoadPointer(cas.redPacketStatisticsPtr))
		fmt.Println("old value: ", oldRedPacketStatistics)
		if oldRedPacketStatistics.GivePeopleNum > RedPacketsNum {
			responseMap["message"] = "sorry. you did not grab the red packet."
			responseMap["success"] = true
			ResponseJson(w, http.StatusOK, responseMap)
			return
		}

		if oldRedPacketStatistics.GiveMoney+RedPacketAvgMoney > RedPacketMoney {
			responseMap["message"] = "the red packet was robbed!"
			responseMap["success"] = true
			ResponseJson(w, http.StatusOK, responseMap)
			return
		}
		newRedPacketStatistics.GiveMoney = oldRedPacketStatistics.GiveMoney + RedPacketAvgMoney
		newRedPacketStatistics.GivePeopleNum = oldRedPacketStatistics.GivePeopleNum + 1
		fmt.Println("new: ", newRedPacketStatistics)
		newRedPacketStatisticsPtr := unsafe.Pointer(&newRedPacketStatistics)
		if atomic.CompareAndSwapPointer(cas.redPacketStatisticsPtr, *cas.redPacketStatisticsPtr, newRedPacketStatisticsPtr) {
			responseMap["message"] = "Congratulations, you have grabbed the red packet!"
			responseMap["success"] = true
			responseMap["time"] = time.Now().Format("2006-01-01 15:04:05")
			responseMap["money"] = RedPacketAvgMoney
			ResponseJson(w, http.StatusOK, responseMap)
			return
		}
	}
}
